﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Nirvana
{
    public sealed class SpriteCache
    {
        private static Logger logger = LogSystem.GetLogger("SpriteCache");
        private Sprite sprite;
        private float defaultReleaseAfterFree = 30f;
        private float lastFreeTime = -1f;

        private bool isLoaded;
        private Dictionary<Sprite, SpriteCache> spriteCacheMap;
        public AssetID AssetID { get; private set; }
        public int ReferenceCount { get; private set; }
        public float LastFreeTime
        {
            get
            {
                return lastFreeTime;
            }
        }
        public float ReleaseAfterFree { get; private set; }
        public bool IsSync { get; set; }
        public string Error { get; private set; }
        public bool Loading { get; set; }

        public SpriteCache(AssetID assetid, Dictionary<Sprite, SpriteCache> datamap)
        {
            this.AssetID = assetid;
            this.spriteCacheMap = datamap;
        }

        public void SetReleaseTimeAfterFree(float t)
        {
            this.defaultReleaseAfterFree = t;
            this.ReleaseAfterFree = t;
        }

        public void Retain()
        {
            ReferenceCount++;
        }

        public void Release()
        {
            ReferenceCount--;
            lastFreeTime = Time.time;
            if(ReferenceCount < 0)
            {
                Debug.LogErrorFormat("[SpriteCache] referenceCount is error {0}, ReferenceCount：{1}",
                    this.AssetID.ToString(), this.ReferenceCount);
            }
        }

        public void Load(AssetID assetID)
        {
            this.Loading = true;
            this.AssetID = assetID;
            Scheduler.RunCoroutine(WaitLoad(assetID));
        }

        public bool IsNotNull()
        {
            return this.sprite != null;
        }

        public Sprite GetObject()
        {
            return this.sprite;
        }

        private IEnumerator WaitLoad(AssetID assetID)
        {
            WaitLoadObject waitLoadObject = null;
            if (this.IsSync)
            {
                waitLoadObject = AssetManager.LoadObjectSync(assetID, typeof(Sprite));
            }else
            {
                waitLoadObject = AssetManager.LoadObject(assetID, typeof(Sprite));
            }
            yield return waitLoadObject;

            if (!string.IsNullOrEmpty(waitLoadObject.Error))
            {
                this.Error = waitLoadObject.Error;
                yield break;
            }

            this.sprite = (waitLoadObject.GetObject() as Sprite);
		
            if (this.sprite == null)
            {
                this.Error = string.Format("The asset {0} is not a Sprite.", assetID);
                yield break;
            }
            ReleaseAfterFree = defaultReleaseAfterFree;
			isLoaded = true;
            if (spriteCacheMap.ContainsKey(this.sprite))
            {
                logger.LogWarning("The sprite {0} has been loaded.", assetID);
                this.spriteCacheMap[this.sprite] = this;
            }else
            {
                this.spriteCacheMap.Add(this.sprite,this);
            }

            yield break;

        }

    }
}

